[% setvar title Short-circuiting built-in functions and user-defined subroutines %]
<div id="archive-notice">
    <h3>This file is part of the Perl 6 Archive</h3>
    <p>To see what is currently happening visit <a href="http://www.perl6.org/">http://www.perl6.org/</a></p>
</div>
<div class='pod'>
<a name='TITLE'></a><h1>TITLE</h1>
<p>Short-circuiting built-in functions and user-defined subroutines</p>
<a name='VERSION'></a><h1>VERSION</h1>
<pre>  Maintainer: Garrett Goebel &lt;<a href='mailto:garrett@scriptpro.com'>garrett@scriptpro.com</a>&gt;
  Date: 6 Sep 2000
  Last Modified: 15 Sep 2000
  Mailing List: <a href='mailto:perl6-language@perl.org'>perl6-language@perl.org</a>
  Number: 199
  Version: 4
  Status: Frozen</pre>
<a name='ABSTRACT'></a><h1>ABSTRACT</h1>
<p>Allow built-in functions and user defined subroutines to catch exceptions
and act upon them, particularly those emanating from control blocks. Put
another way, allow blocks to simultaneously exit early with a value.</p>
<a name='DESCRIPTION'></a><h1>DESCRIPTION</h1>
<a name='OVERVIEW'></a><h2>OVERVIEW</h2>
<p>Currently there is not a practical and flexible way to short-circuit
built-in functions like <code>grep</code> and <code>map</code> which take blocks as a parameter.</p>
<p>A prime example that was raised is:</p>
<pre>  my $found = grep { $_ == 1 } (1..1_000_000);</pre>
<p>Under Perl 5, one would need to write something like:</p>
<pre>  eval { grep { $_ ==1 and die &quot;$_\n&quot; } (1..1_000_000) }; 
  chomp(my $found = $@);</pre>
<p>Under this current proposal this might be written as:</p>
<pre>  my $found = grep { $_ == 1 and return $_ &amp;&amp; last grep } (1..1_000_000);

  (or alternatively)

  my $found = grep { $_ == 1 and abort grep $_ } (1..1_000_000);</pre>
<p>It is the opinion of the author that while the proposal saves little by
way of typing, that it is minimally an improvement in clarity. Further
this proposal introduces semantics which will make other tasks easier.</p>
<a name='DEFINITION OF THE PROBLEM'></a><h2>DEFINITION OF THE PROBLEM</h2>
<ul>
<li><a name='1'></a>1</li>
<p>How do you simultaneously exit early and return a value?</p>
<pre>  reject the current element and continue
  accept the current element and continue
  reject the current element and abort
  accept the current element and abort
  reject the current element and retry
  accept the current element and retry</pre>
<li><a name='2'></a>2</li>
<p>How do you do that *and* be consistent with existing semantics?</p>
</ul>
<a name='OPTIONS AND ALTERNATIVES'></a><h2>OPTIONS AND ALTERNATIVES</h2>
<p>There has been much discussion and ideas exchanged on the best way to
achieve this. Discussion ranging from specific solutions which would
only apply to the <code>grep</code> and <code>map</code> built-ins, to more general ones
such as unifying the exception syntax for loop, code, and bare blocks.
There has also been a vocal contingent protesting that all of the
suggestions attempt to shoehorn too much new functionality into
existing semantics and that no one has yet presented any workable
solutions.</p>
<p>The current ideas tend to converge around the following three options:</p>
<ul>
<li><a name='1'></a>1</li>
<p>Grant code blocks their names as labels, and add new keywords
for code block control: <code>continue</code>/<code>abort</code>/<code>retry</code>:</p>
<pre>  # short-circuit after first acceptance...
  $found = grep { ($_ == 1) and abort grep $_ } (1..1_000_000);

  # short-circuit after first rejection...
  $found = grep { ($_ == 1) and abort grep } (1..1_000_000);</pre>
<li><a name='2'></a>2</li>
<p>Grant code blocks their own names as labels, and the ability to catch
next/last/redo exceptions which explicitly use those labels.</p>
<pre>  # short-circuit after first acceptance...
  @smalls = grep { ($_ == 1) and return $_ &amp;&amp; last grep } (1..1_000_000);

  # short-circuit after first rejection...
  @smalls = grep { ($_ == 1) and last grep } (1..1_000_000);</pre>
<li><a name='3'></a>3</li>
<p>The built-in function's operation should catch exceptions thrown from
the block, where the exception thrown is true or false (alternative: 1
or false). Example:</p>
<pre>  # short-circuit after first acceptance...
  $found = grep { ($_ == 1) and die 1 } (1..1_000_000);

  # short-circuit after first rejection...
  $found = grep { ($_ == 1)  or die 0 } (1..1_000_000);</pre>
</ul>
<a name='INDECISIONS: BY THE PRICKINGS OF MY THUMB...'></a><h2>INDECISIONS: BY THE PRICKINGS OF MY THUMB...</h2>
<p>Detractors would argue:</p>
<ul>
<li><a name='1'></a>1</li>
<p>First Proposal: Add code labels and new keywords: <code>continue</code>/<code>abort</code>/<code>retry</code></p>
<ul>
<li><a name='Aversion to taking any more new keywords'></a>Aversion to taking any more new keywords</li>
</ul>
<li><a name='2'></a>2</li>
<p>Second Proposal: Add code labels, and let code blocks use
<code>next</code>/<code>last</code>/<code>redo</code> syntax which explicitly use those labels.</p>
<ul>
<li><a name='Too complicated, changes too much, attempts to shoehorn to too many semantic changes into the existing syntax/keywords'></a>Too complicated, changes too much, attempts to shoehorn to too many
semantic changes into the existing syntax/keywords</li>
</ul>
<li><a name='3'></a>3</li>
<p>Third Proposal: Extend use of <code>die</code></p>
<ul>
<li><a name='Built-ins shouldn't catch user-defined exceptions. How do you raise a serious exception within a control block if you weaken die into something that can be automatically caught by built-ins? I.e., no good support for multi-level exceptions.'></a>Built-ins shouldn't catch user-defined exceptions. How do you raise
a serious exception within a control block if you weaken <code>die</code> into
something that can be automatically caught by built-ins? I.e., no good
support for multi-level exceptions.</li>
<li><a name='Doesn't provide a very intuitive syntax for doing the same type of next/last/redo control as is available with loop blocks.'></a>Doesn't provide a very intuitive syntax for doing the same type of
<code>next</code>/<code>last</code>/<code>redo</code> control as is available with loop blocks.</li>
</ul>
</ul>
<p>The author shares much of detractors opinions for the third proposal, and
would prefer either the first or second to be implemented. The reason I prefer
one of these two is that I believe they are more intuitive, flexible, and
semantically rich. As such, the remainder of this RFC concern itself with
issues pertaining to the first two proposals.</p>
<a name='FINER DETAILS AND OTHER ISSUES'></a><h2>FINER DETAILS AND OTHER ISSUES</h2>
<a name='Issues common to the first and second proposals:'></a><h3>Issues common to the first and second proposals:</h3>
<ul>
<li><a name='Built-ins and Subroutines automatically get their name as a label'></a>Built-ins and Subroutines automatically get their name as a label</li>
<p>It might therefore follow that it would be good to define <code>goto foo</code> to
have the same semantics as <code>goto &amp;foo</code> when the label referred to is a
function. Namely to pass @_. It would then be possible if desired to
deprecate <code>goto &amp;foo</code>.</p>
<li><a name='To support multi-level escaping, explicit named or numeric labels may be used. Where numeric labels specify the level of nesting to be escaped similarly to caller. 0 refers to the current code block, 1 the caller's, and so forth. Otherwise undef may also be used to refer to the current code block.'></a>To support multi-level escaping, explicit named or numeric labels may
be used. Where numeric labels specify the level of nesting to be
escaped similarly to <code>caller</code>. 0 refers to the current code block,
1 the caller's, and so forth. Otherwise <code>undef</code> may also be used to refer
to the current code block.</li>
<p>Regardless of whether or not this proposal is implemented, it might be
nice to add the same numeric label semantics when labels are used with loop
control statements.</p>
<p>Examples:</p>
<pre>  sub func1 { @_ ? &amp;func2 : abort undef, 0 }
  sub func2 { $_[0] eq undef ? abort func1, 0 : &amp;func3 }
  sub func3 { $_[0] eq 'foo' ? abort 2, 0 : 1 }</pre>
<li><a name='The idea of being able to both short-circuit a block and return a value may create confusion as to the context in which the value is being returned. I've slightly modified one of John Porters examples which illustrate the various blocks and their controls:'></a>The idea of being able to both short-circuit a block and return a value
may create confusion as to the context in which the value is being returned.
I've slightly modified one of John Porters examples which illustrate the
various blocks and their controls:</li>
<pre>  sub foo {               # Code Block  
    eval {                # Bare Block
      for (...) {         # Loop Block
  
        last &amp;&amp; return 1; # Note: all
        die &amp;&amp; return 1;  # of these go
        abort 1, 1        # to different
        return 1;         # places
  
      }
    };
  }</pre>
<p>This example doesn't confuse the author. But that isn't to say that others
won't find it confusing.</p>
</ul>
<a name='Issues specific to adding code block control statements'></a><h3>Issues specific to adding code block control statements</h3>
<ul>
<li><a name='When using code block control statements, labels are required but return values are not. This is necessary to support optionally passing a return value.'></a>When using code block control statements, labels are required but return
values are not.  This is necessary to support optionally passing a return
value.</li>
</ul>
<a name='Issues specific to adding support for loop control syntax to code control'></a><h3>Issues specific to adding support for loop control syntax to code control</h3>
<ul>
<li><a name='Let return $value &amp;&amp; next LABEL be used to support both short-circuiting and returning a value'></a>Let <code>return $value &amp;&amp; next LABEL</code> be used to support both short-circuiting
and returning a value</li>
<p>There was some consensus that <code>return</code> is a good fit for returning a value
from a control block. But it doesn't support multi-level escaping. Therefore
the use of loop control syntax is tacked on. The question becomes if both
<code>return</code> and <code>last</code> are both exceptions which exit the block early, how
do you catch them both and handle them appropriately? Is <code>&amp;&amp;</code> sufficient
to the cause? From the author's perspective it looks fine and dandy. But I
have little or no idea how this would work in regard to Perl internals.</p>
<li><a name='Need to stop calling them loop control statements and start referring to them as short-circuit or statements commonly used with loop control'></a>Need to stop calling them loop control statements and start referring to
them as short-circuit or statements commonly used with loop control</li>
<li><a name='Optionally, we might also consider allowing people to both raise an exception with die &amp;&amp; return $value'></a>Optionally, we might also consider allowing people to both raise an
exception with <code>die</code> &amp;&amp; <code>return</code> $value</li>
</ul>
<a name='BACKWARD COMPATIBILITY ISSUES'></a><h2>BACKWARD COMPATIBILITY ISSUES</h2>
<p>If loop control syntax is grafted on for use with code blocks, then
a Perl 5 -&gt; 6 translator would need to explicitly label all loop
blocks and loop control statements.</p>
<a name='IMPLEMENTATION'></a><h1>IMPLEMENTATION</h1>
<p>I haven't a clue.</p>
<a name='REFERENCES'></a><h1>REFERENCES</h1>
<p>Too many contributors to note them all down. The content of this RFC owes
heavily to list discussions. The author has simply tried to pick and choose
the best and most easily grasped ideas and analyses from the list.</p>
<ul>
<li><a name='RFC's that require this functionality'></a>RFC's that require this functionality</li>
<p>RFC 76: Builtin: reduce</p>
<li><a name='Ideas that offer alternative routes to similar functionality:'></a>Ideas that offer alternative routes to similar functionality:</li>
<p>RFC 22: Control flow: Builtin switch statement</p>
<p>RFC 31: Subroutines: Co-routines</p>
<p>RFC 123: Builtin: lazy</p>
<p>RFC 225: Data: Superpositions</p>
</ul>
</div>
